import datetime

from odoo import fields, models, api, _
from odoo.tools.float_utils import float_compare, float_is_zero
from odoo.exceptions import ValidationError, UserError


class QualityAlert(models.Model):
    _inherit = 'quality.alert'
    _order = 'id desc'

    s_production_id = fields.Many2one(
        'mrp.production', string='Production', required=True, copy=False,
        domain=[('state', 'in', ('confirmed', 'progress', 'to_close'))]
    )
    s_workorder_id = fields.Many2one('mrp.workorder', 'Work Order', required=True, copy=False)
    s_step = fields.Integer(string="Procedures", related='s_workorder_id.step')
    s_work_station_id = fields.Many2one('work.station', string="Work Station")
    s_qty_wip = fields.Integer('Work In Process (WIP)', copy=False)
    s_qty_wip_set = fields.Integer('Work In Process (SET)', copy=False)
    s_qty_wip_pnl = fields.Integer('Work In Process (PNL)', copy=False)
    s_scrap_ids = fields.One2many('s.workorder.scrap.record', 'quality_alert_id')
    s_return_scrap_ids = fields.One2many('s.workorder.return.scrap.record', 'quality_alert_id')

    s_panel_pcs = fields.Integer(string='PANEL/PCS', related='s_production_id.s_value_pnl')
    s_set_pcs = fields.Integer(string='SET/PCS', related='s_production_id.s_value_set')
    # 外包数量
    subcon_qty = fields.Integer(string='Qty Subcon')
    # 良品
    good_subcon_qty = fields.Integer(string='Qty Subcon Good')
    # 报废品
    poor_subcon_qty = fields.Integer(string='Qty Subcon Poor')

    s_state = fields.Selection([
        ('draft', 'draft'),
        ('confirm', 'confirm')
    ], string='s_state', default='draft', readonly=True, copy=False)
    s_mes_code = fields.Char(string='mes报废单号')
    s_is_return = fields.Boolean(default=False)

    s_confirm_date = fields.Datetime('Confirm Date', copy=False, readonly=True)

    @api.onchange('s_production_id')
    def onchange_production_id(self):
        if not self.s_production_id:
            return
        workorder_ids = self.s_production_id.workorder_ids.filtered(lambda x: x.qty_wip > 0)
        if not workorder_ids:
            return {
                'warning': {
                    'title': _('Warning'),
                    'message': _('Production order without online quantity')
                }
            }
        else:
            workorder = workorder_ids[0]
            if workorder.workcenter_id.code and workorder.workcenter_id.code == 'PKG01':
                raise UserError(_('The packaging process does not allow scrapping'))
            self.write({
                's_workorder_id': workorder.id,
                'product_id': self.s_production_id.product_id.id,
                'product_tmpl_id': self.s_production_id.product_id.product_tmpl_id.id,
                's_work_station_id': workorder.workcenter_id.work_station_id.id,
                'workcenter_id': workorder.workcenter_id.id,
                's_qty_wip': workorder.qty_wip,
                's_qty_wip_set': workorder.qty_wip_set,
                's_qty_wip_pnl': workorder.qty_wip_pnl,
            })

    @api.constrains('s_scrap_ids')
    def check_scrap_ids(self):

        for rec in self:
            if rec.s_mes_code: continue
            qty = sum(rec.s_scrap_ids.mapped('scrap_qty'))
            set_ = sum(rec.s_scrap_ids.mapped('scrap_set_qty'))
            panel = sum(rec.s_scrap_ids.mapped('scrap_panel_qty'))
            rounding = rec.s_production_id.product_uom_id.rounding
            if float_is_zero(qty, precision_rounding=rounding):
                raise ValidationError(_('The scrap quantity is zero!'))

            # 取最新的值
            workorder_qty_wip = rec.s_workorder_id.qty_wip
            workorder_qty_wip_set = rec.s_workorder_id.qty_wip_set
            workorder_qty_wip_pnl = rec.s_workorder_id.qty_wip_pnl
            if float_compare(qty, workorder_qty_wip, precision_rounding=rounding) == 1:
                raise ValidationError(_('The number of scrapped items cannot exceed the number of online items!'))

            if float_compare(set_, workorder_qty_wip_set, precision_rounding=rounding) == 1:
                raise ValidationError(_('The number of scrapped items (SET) cannot exceed the number of online items!'))

            if float_compare(panel, workorder_qty_wip_pnl, precision_rounding=rounding) == 1:
                raise ValidationError(
                    _('The number of scrapped items (PANEL) cannot exceed the number of online items!'))

    @api.constrains('stage_id')
    def constrains_stage_id(self):
        confirmed_stage_id = self.env.ref('quality.quality_alert_stage_1')

        for rec in self:
            if rec.stage_id == confirmed_stage_id:
                # rec.s_state = 'confirm'
                rec.s_scrap_ids.write({'workorder_id': rec.s_workorder_id.id})

    def unlink(self):
        new_stage_id = self.env.ref('quality.quality_alert_stage_0')
        for rec in self:
            if rec.stage_id != new_stage_id:
                raise UserError(_('This status (%s) does not allow deletion', rec.stage_id.name))
            rec.s_scrap_ids.sudo().unlink()

        return super().unlink()

    def action_confirm(self):
        confirmed_stage_id = self.env.ref('quality.quality_alert_stage_1')
        for rec in self:
            if rec.s_workorder_id.state == 'done':
                raise UserError(_('%s is done, Please confirm after returning the order!', rec.s_workorder_id.name))
        self.filtered(lambda x: x.s_state == 'draft').write({
            's_state': 'confirm',
            'stage_id': confirmed_stage_id.id,
            's_confirm_date': datetime.datetime.now()
        })
        self.mapped('s_production_id').with_delay().scrap_warning()

    def action_revocation(self):
        self.ensure_one()
        if self.s_workorder_id.state == 'done':
            raise UserError(_('The process report has been completed, please notify the production to return the order before withdrawing it'))
        confirmed_stage_id = self.env.ref('quality.quality_alert_stage_0')
        self.write({
            's_state': 'draft',
            'stage_id': confirmed_stage_id.id,
            's_confirm_date': False
        })
        self.s_scrap_ids.write({'workorder_id': False})
        self.s_workorder_id.compute_qty_floor()
